home *** CD-ROM | disk | FTP | other *** search
- /* IP-related user commands
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by PA0GRI */
- #include "global.h"
- #include "commands.h"
- #include "mbuf.h"
- #include "internet.h"
- #include "timer.h"
- #include "netuser.h"
- #include "iface.h"
- #include "session.h"
- #include "rspf.h"
- #include "domain.h"
- #include "pool.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: ipcmd.c,v 1.21 1997/09/07 00:31:16 root Exp root $";
- #endif
-
- uint32 Ip_addr;
- static int Route_Sort = 1;
- int Route_Same = 0;
-
-
- static int doadd (int argc, char *argv[], void *p);
-
- #ifdef IPACCESS
- static int doaccess (int argc, char *argv[], void *p);
- #endif
-
- static int dodrop (int argc, char *argv[], void *p);
- static int doflush (int argc, char *argv[], void *p);
- static int doipaddr (int argc, char *argv[], void *p);
- static int doipstat (int argc, char *argv[], void *p);
- static int doiplook (int argc, char *argv[], void *p);
- static int dortimer (int argc, char *argv[], void *p);
- static int dottl (int argc, char *argv[], void *p);
- static int doiphport (int argc, char *argv[], void *p);
- static int doiphsize (int argc, char *argv[], void *p);
- void dumproute (struct route * rp, char *p);
- static int doroutesort (int argc, char *argv[], void *p);
- static int doroutesame (int argc, char *argv[], void *p);
-
- /* IP heard logging - WG7J */
- static struct iph *iph_create (uint32 addr);
- static struct iph *iph_lookup (uint32 addr);
- static struct iph *Iph = NULLIPH;
-
- static int Maxipheard = MAXIPHEARD;
-
-
- #ifdef CATALOG
- #include "catalog.h"
-
- #define CAT ipcmd_catalog
-
- #define accesshdr __STR(0)
- #define accesssyntax __STR(1)
- #define rtimerstr __STR(2)
- #define ttlstr __STR(3)
- #define iplookstr __STR(4)
- #define reassembly __STR(5)
- #define notfound __STR(6)
- #define noaddroute __STR(7)
- #define heardhdr __STR(8)
- #define sortstr __STR(9)
- #define iphsizestr __STR(10)
- #define samestr __STR(11)
-
- #else /* CATALOG */
- static const char accesshdr[] = "Source Address Len Dest Address Len Interface Proto Low High State\n";
- static const char accesssyntax[] = " Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n";
- static const char rtimerstr[] = "IP reasm timeout (sec)";
- static const char ttlstr[] = "IP Time-to-live";
- static const char iplookstr[] = "Host %s (%s) unreachable\n";
- static const char reassembly[] = "Reassembly fragments:\n";
- static const char notfound[] = "Not found.\n";
- static const char noaddroute[] = "Can't add route\n";
- static const char heardhdr[] = "Tcp/Ip systems heard:\nAddress Port Since Pkts\n";
- static const char sortstr[] = "Route Sort flag";
- static const char iphsizestr[] = "Max ip-heard";
- static const char samestr[] = "Permit IP routing out same interface it was received";
- #endif /* CATALOG */
-
-
- static const char allstr[] = "all";
- static const char anystr[] = "any";
- static const char icmpstr[] = "icmp";
- static const char tcpstr[] = "tcp";
- static const char udpstr[] = "udp";
- static const char denystr[] = "deny";
- static const char permitstr[] = "permit";
- static const char deletestr[] = "delete";
- static const char strCR[] = "%s\n";
- static const char defaultstr[] = "default";
- static const char rspfstr[] = "rspf ";
- static const char manstr[] = "man ";
- static const char directstr[] = "direct";
- static const char statdata[] = "(%2u)%-20s%10lu";
- static const char re_src[] = "src %s";
- static const char re_dest[] = " dest %s";
- static const char re_id[] = " id %u pctl %u time %lu len %u\n";
- static const char re_off[] = " offset %u last %u\n";
- static const char hearddata[] = "%-22s %-8s %12s %5ld\n";
- const char RouteHeader[] = "Destination Len Interface Gateway Metric P Timer Use\n";
-
-
- #ifdef POOLED
- static struct mempool iph_pool = {NULLPOOLBLK, NULLPOOLBLK, 0, sizeof (struct iph), 50};
- #endif
-
-
-
-
- static struct cmds Ipcmds[] =
- {
- #ifdef IPACCESS
- { "access", doaccess, 0, 0, NULLCHAR },
- #endif
- { "address", doipaddr, 0, 0, NULLCHAR },
- { "heard", doipheard, 0, 0, NULLCHAR },
- { "hport", doiphport, 0, 0, NULLCHAR },
- { "hsize", doiphsize, 0, 0, NULLCHAR },
- { "routesame", doroutesame, 0, 0, NULLCHAR },
- { "rtimer", dortimer, 0, 0, NULLCHAR },
- { "status", doipstat, 0, 0, NULLCHAR },
- { "ttl", dottl, 0, 0, NULLCHAR },
- { NULLCHAR, NULL, 0, 0, NULLCHAR }
- };
-
-
-
- /* "route" subcommands */
- static struct cmds Rtcmds[] =
- {
- { "add", doadd, 0, 3, "route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]" },
- { "addprivate", doadd, 0, 3, "route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]"},
- { "drop", dodrop, 0, 2, "route drop <dest addr>[/<bits>]" },
- { "flush", doflush, 0, 0, NULLCHAR },
- { "lookup", doiplook, 0, 2, "route lookup <dest addr>" },
- { "sort", doroutesort, 0, 0, NULLCHAR },
- { NULLCHAR, NULL, 0, 0, NULLCHAR }
- };
-
-
-
- int
- doip (int argc, char *argv[], void *p)
- {
- return subcmd (Ipcmds, argc, argv, p);
- }
-
-
-
- #ifdef IPACCESS
- static int
- doaccess (int argc, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
- uint32 source, target;
- unsigned sbits, tbits;
- char *bitp;
- int16 lport, hport, protocol, state;
- char const *cp; /* for printing the table */
- struct rtaccess *tpacc;
- struct rtaccess *btacc;
- struct rtaccess *bfacc;
- struct rtaccess *head;
- char tmpbuf[15];
-
- if (argc == 1) { /* print out the table */
- tputs (accesshdr);
- for (tpacc = IPaccess; tpacc != NULLACCESS; tpacc = tpacc->nxtiface) {
- for (btacc = tpacc; btacc != NULLACCESS; btacc = btacc->nxtbits) {
- if (btacc->source != 0)
- cp = inet_ntoa (btacc->source);
- else
- cp = allstr;
- tprintf ("%-16s%2u ", cp, btacc->sbits);
- if (btacc->target != 0)
- cp = inet_ntoa (btacc->target);
- else
- cp = allstr;
- tprintf ("%-16s%2u %-13s", cp, btacc->bits, btacc->iface->name);
- switch (btacc->protocol) {
- case 0: cp = anystr;
- break;
- case ICMP_PTCL: cp = icmpstr;
- break;
- case TCP_PTCL: cp = tcpstr;
- break;
- case UDP_PTCL: cp = udpstr;
- break;
- default: cp = itoa (btacc->protocol, tmpbuf, 10);
- }
- tprintf ("%-5s %5u %5u ", cp, btacc->lowport, btacc->highport);
- if (btacc->status)
- cp = denystr;
- else
- cp = permitstr;
- tprintf ("%-6s\n", cp);
- }
- }
- return 0;
- }
- if (strcmp (argv[1], permitstr) == 0)
- state = 0;
- else {
- if ((strcmp (argv[1], denystr) == 0) || (strcmp (argv[1], deletestr) == 0))
- state = (int16) - 1;
- else {
- tputs (accesssyntax);
- return 1;
- }
- }
-
- if (argc < 6) {
- tputs (accesssyntax);
- return 1;
- }
- switch (*argv[2]) {
- case 'a': /* ANY */
- protocol = 0;
- break;
- case 'i': /* ICMP */
- protocol = ICMP_PTCL;
- break;
- case 't': /* TCP */
- protocol = TCP_PTCL;
- break;
- case 'u': /* UDP */
- protocol = UDP_PTCL;
- break;
- default:
- protocol = (int16) atoi (argv[2]);
- }
-
- if (strcmp (argv[3], allstr) == 0) {
- source = 0;
- sbits = 0;
- } else {
- /* If IP address is followed by an optional slash and
- * a length field, (e.g., 128.96/16) get it;
- * otherwise assume a full 32-bit address
- */
- if ((bitp = strchr (argv[3], '/')) != NULLCHAR) {
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- sbits = (unsigned int) atoi (bitp);
- } else
- sbits = 32;
-
- if ((source = resolve (argv[3])) == 0) {
- tprintf (Badhost, argv[3]);
- return 1;
- }
- }
- if (strcmp (argv[4], allstr) == 0) {
- target = 0;
- tbits = 0;
- } else {
- if ((bitp = strchr (argv[4], '/')) != NULLCHAR) {
- *bitp++ = '\0';
- tbits = (unsigned int) atoi (bitp);
- } else
- tbits = 32;
-
- if ((target = resolve (argv[4])) == 0) {
- tprintf (Badhost, argv[4]);
- return 1;
- }
- }
-
- if ((ifp = if_lookup (argv[5])) == NULLIF) {
- tprintf (Badinterface, argv[5]);
- return 1;
- }
- if (((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
- lport = 0;
- hport = 0;
- } else {
- if (strcmp (argv[6], allstr) == 0)
- lport = 0;
- else
- lport = (int16) atoi (argv[6]);
-
- if ((argc < 8) || (lport == 0))
- hport = lport;
- else
- hport = (int16) atoi (argv[7]);
- }
-
- if (strcmp (argv[1], deletestr) == 0) {
- head = IPaccess;
- for (tpacc = IPaccess; tpacc != NULLACCESS; head = tpacc, tpacc = tpacc->nxtiface) {
- if (tpacc->iface == ifp) {
- for (btacc = tpacc; btacc != NULLACCESS; head = btacc, btacc = btacc->nxtbits) {
- if ((btacc->protocol == protocol) &&
- (btacc->source == source) &&
- (btacc->sbits == sbits) &&
- (btacc->target == target) &&
- (btacc->bits == tbits) &&
- (btacc->lowport == lport) &&
- (btacc->highport == hport)) { /*match*/
- bfacc = btacc; /* save to unalloc */
- /*now delete. watch for special cases*/
- if (btacc != tpacc) { /* not at head of list */
- head->nxtbits = btacc->nxtbits;
- free (bfacc);
- return 0;
- }
- if (btacc == IPaccess) { /* real special case */
- if (IPaccess->nxtbits == NULLACCESS)
- IPaccess = btacc->nxtiface;
- else {
- IPaccess = btacc->nxtbits;
- (btacc->nxtbits)->nxtiface = btacc->nxtiface;
- }
- } else { /* we know tpacc=btacc <> IPaccess */
- if (btacc->nxtbits == NULLACCESS)
- head->nxtiface = btacc->nxtiface;
- else {
- head->nxtiface = btacc->nxtbits;
- (btacc->nxtbits)->nxtiface = btacc->nxtiface;
- }
- }
- free (bfacc);
- return 0;
- }
- }
- }
- }
- tputs (notfound);
- return 1;
- }
- /* add the access */
- addaccess (protocol, source, sbits, target, tbits, ifp, lport, hport, state);
- return 0;
- }
- #endif
-
-
-
- static int
- doipaddr (int argc, char *argv[], void *p OPTIONAL)
- {
- uint32 n;
-
- if (argc < 2)
- tprintf (strCR, inet_ntoa (Ip_addr));
- else if ((n = resolve (argv[1])) == 0) {
- tprintf (Badhost, argv[1]);
- return 1;
- } else
- Ip_addr = n;
- return 0;
- }
-
-
-
- static int
- dortimer (int argc, char *argv[], void *p OPTIONAL)
- {
- return setlong ((long *)&ipReasmTimeout, rtimerstr, argc, argv);
- }
-
-
-
- static int
- dottl (int argc, char *argv[], void *p OPTIONAL)
- {
- return setlong ((long *)&ipDefaultTTL, ttlstr, argc, argv);
- }
-
-
- /* Display and/or manipulate routing table */
- int
- doroute (int argc, char *argv[], void *p)
- {
- register int i, j, k, bits, flow_tmp;
- register struct route *rp;
- char *temp, temp2[80];
-
- if (argc >= 2)
- return subcmd (Rtcmds, argc, argv, p);
-
- /* Dump IP routing table
- * Dest Len Interface Gateway Use
- * 192.001.002.003 32 sl0 192.002.003.004 0
- * modified for Sorted output - D. Crompton 2.92
- */
-
- flow_tmp = Current->flowmode;
- Current->flowmode = 1;
-
- tputs (RouteHeader);
-
- for (j = 0, bits = 31; bits >= 0; bits--)
- for (i = 0; i < HASHMOD; i++)
- for (rp = Routes[bits][i]; rp != NULLROUTE; j++, rp = rp->next)
- ;
-
- if (j) {
-
- temp = mallocw ((unsigned) j * 80);
-
- for (bits = 31, k = 0; bits >= 0; bits--)
- for (i = 0; i < HASHMOD; i++)
- for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next, k += 80)
- dumproute (rp, &temp[k]);
-
- if (Route_Sort)
- qsort (temp, (size_t) j, 80, (int (*)(const void *, const void *)) strcmp);
-
- for (i = 0, k = 4; i < j; i++, k += 80) {
- tputs (&temp[k]);
- if (tputc ('\n') == EOF) {
- Current->flowmode = flow_tmp;
- free (temp);
- return 0;
- }
- }
- free (temp);
- }
- if (R_default.iface != NULLIF) {
- dumproute (&R_default, temp2);
- tprintf (strCR, &temp2[4]);
- }
- Current->flowmode = flow_tmp;
- return 0;
- }
-
-
-
- /* Dump a routing table entry */
- void
- dumproute (register struct route *rp, char *temp)
- {
- char const *cp;
- unsigned int a = 4;
- char *name;
-
- if (rp->target != 0) {
- if (DTranslate && (name = resolve_a (rp->target, !DVerbose)) != NULLCHAR) {
- strcpy (temp, name);
- free (name);
- } else {
- cp = inet_ntobos (rp->target);
- a = (unsigned int) SPRINTF ((temp, "%4s", cp));
- }
- cp = inet_ntoa (rp->target);
- } else {
- strcpy (temp, defaultstr); /* Don't really matter, but avoid unknown value */
- cp = "default";
- }
- a += (unsigned int) SPRINTF ((&temp[a], "%-16.16s ", cp));
- a += (unsigned int) SPRINTF ((&temp[a], "%-4u", rp->bits));
- a += (unsigned int) SPRINTF ((&temp[a], "%-9.9s ", rp->iface->name));
- if (rp->gateway != 0)
- cp = inet_ntoa (rp->gateway);
- else
- cp = "";
- a += (unsigned int) SPRINTF ((&temp[a], "%-16.16s ", cp));
- a += (unsigned int) SPRINTF ((&temp[a], "%-6lu ", rp->metric));
- a += (unsigned int) SPRINTF ((&temp[a], "%c ", (rp->flags & RTPRIVATE) ? 'P' : ' '));
- if (rp->timer.state == TIMER_STOP) {
- if (rp->timer.duration == 1)
- a += (unsigned int) SPRINTF ((&temp[a], rspfstr));
- else
- a += (unsigned int) SPRINTF ((&temp[a], manstr));
- } else
- a += (unsigned int) SPRINTF ((&temp[a], "%-7lu", read_timer (&rp->timer) / 1000L));
- sprintf (&temp[a], "%lu", rp->uses);
- }
-
-
-
- /* Sort Route dump */
- static int
- doroutesort (int argc, char *argv[], void *p OPTIONAL)
- {
- return setbool (&Route_Sort, sortstr, argc, argv);
- }
-
-
- static int
- doroutesame (int argc, char *argv[], void *p OPTIONAL)
- {
- return setbool (&Route_Same, samestr, argc, argv);
- }
-
-
- /* Add an entry to the routing table
- * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
- */
- static int
- doadd (int argc, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
- uint32 dest, gateway;
- unsigned bits;
- char *bitp;
- int32 metric;
- char private;
-
- if (strncmp (argv[0], "addp", 4) == 0)
- private = 1;
- else
- private = 0;
- if (strcmp (argv[1], defaultstr) == 0) {
- dest = 0L;
- bits = 0;
- } else {
- /* If IP address is followed by an optional slash and
- * a length field, (e.g., 128.96/16) get it;
- * otherwise assume a full 32-bit address
- */
- if ((bitp = strchr (argv[1], '/')) != NULLCHAR) {
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- bits = (unsigned int) atoi (bitp);
- } else
- bits = 32;
-
- if ((dest = resolve (argv[1])) == 0) {
- tprintf (Badhost, argv[1]);
- return 1;
- }
- }
- if ((ifp = if_lookup (argv[2])) == NULLIF) {
- tprintf (Badinterface, argv[2]);
- return 1;
- }
- metric = 1;
-
- if (argc > 3) {
- /* Next "trick is needed to set the metric on subnets
- * higher as the default 1 for rspf.
- * route add subnet/bits iface default 10
- */
- if (strcmp (argv[3], directstr) == 0) { /* N1BEE */
- gateway = 0;
- /* calculate a nice metric based on subnet mask size */
- if (bits != 0 && bits < 32)
- metric = (long) ((39 - bits) * 5 / 17);
- } else {
- if ((gateway = resolve (argv[3])) == 0) {
- tprintf (Badhost, argv[3]);
- return 1;
- }
- }
- } else
- gateway = 0;
-
- if (argc > 4)
- metric = atol (argv[4]);
-
- if (rt_add (dest, bits, gateway, ifp, metric, 0, private) == NULLROUTE)
- tputs (noaddroute);
- #ifdef RSPF
- if (!private)
- rspfrouteupcall (dest, bits, gateway); /* Do an RSPF upcall */
- #endif /* RSPF */
- return 0;
- }
-
-
-
- /* Drop an entry from the routing table
- * E.g., "drop 128.96/16
- */
- static int
- dodrop (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- char *bitp;
- unsigned bits;
- uint32 n;
-
- if (strcmp (argv[1], defaultstr) == 0) {
- n = 0L;
- bits = 0;
- } else {
- /* If IP address is followed by an optional slash and length field,
- * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
- */
- if ((bitp = strchr (argv[1], '/')) != NULLCHAR) {
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- bits = (unsigned int) atoi (bitp);
- } else
- bits = 32;
-
- if ((n = resolve (argv[1])) == 0) {
- tprintf (Badhost, argv[1]);
- return 1;
- }
- }
- return rt_drop (n, bits);
- }
-
-
-
- /* Force a timeout on all temporary routes */
- static int
- doflush (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- register struct route *rp;
- struct route *rptmp;
- int i, j;
-
- if (R_default.timer.state == TIMER_RUN)
- (void) rt_drop (0, 0); /* Drop default route */
-
- for (i = 0; i < HASHMOD; i++) {
- for (j = 0; j < 32; j++) {
- for (rp = Routes[j][i]; rp != NULLROUTE; rp = rptmp) {
- rptmp = rp->next;
- if (rp->timer.state == TIMER_RUN)
- (void) rt_drop (rp->target, rp->bits);
- }
- }
- }
- return 0;
- }
-
-
-
- static int
- doiplook (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct route *rp;
- uint32 addr;
- char temp[80];
-
- addr = resolve (argv[1]);
- if (addr == 0) {
- tprintf (Badhost, argv[1]);
- return 1;
- }
- if ((rp = rt_lookup (addr)) == NULLROUTE) {
- tprintf (iplookstr, argv[1], inet_ntoa (addr));
- return 1;
- }
- dumproute (rp, temp);
- tputs (RouteHeader);
- tprintf (strCR, &temp[4]);
-
- return 0;
- }
-
-
-
- static int
- doipstat (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- register struct reasm *rp;
- register struct frag *fp;
- int i;
-
- for (i = 1; i <= NUMIPMIB; i++) {
- tprintf (statdata, i, Ip_mib[i].name, Ip_mib[i].value.integer);
- if (i % 2)
- tputs (" ");
- else
- tputc ('\n');
- }
- if ((i % 2) == 0)
- tputc ('\n');
-
- if (Reasmq != NULLREASM)
- tputs (reassembly);
- for (rp = Reasmq; rp != NULLREASM; rp = rp->next) {
- tprintf (re_src, inet_ntoa (rp->source));
- tprintf (re_dest, inet_ntoa (rp->dest));
- if (tprintf (re_id, rp->id, uchar (rp->protocol), read_timer (&rp->timer), rp->length) == EOF)
- break;
- for (fp = rp->fraglist; fp != NULLFRAG; fp = fp->next) {
- if (tprintf (re_off, fp->offset, fp->last) == EOF)
- break;
- }
- }
- return 0;
- }
-
-
-
- static int
- doiphsize (int argc, char *argv[], void *p OPTIONAL)
- {
- return setint (&Maxipheard, iphsizestr, argc, argv);
- }
-
-
-
- /* Configure a port to do ip-heard logging */
- static int
- doiphport (int argc, char *argv[], void *p)
- {
- return (dosetflag (argc, argv, p, LOG_IPHEARD, 0));
- }
-
-
-
- int
- doipheard (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- struct iph *iph;
-
- if (tputs (heardhdr) == EOF)
- return EOF;
- for (iph = Iph; iph; iph = iph->next) {
- if (tprintf (hearddata, inet_ntoa (iph->addr), iph->iface->name, tformat (secclock () - iph->time), iph->count) == EOF)
- return EOF;
- }
- return 0;
- }
-
-
-
- void
- log_ipheard (uint32 addr, struct iface *ifp)
- {
- struct iph *niph;
-
- if ((niph = iph_lookup (addr)) == NULLIPH)
- if ((niph = iph_create (addr)) == NULLIPH)
- return;
- niph->iface = ifp;
- niph->count++;
- niph->time = secclock ();
- }
-
-
-
- /* Look up an entry in the ip data base */
- struct iph *
- iph_lookup (uint32 addr)
- {
- register struct iph *ip;
- struct iph *last = NULLIPH;
-
- for (ip = Iph; ip != NULLIPH; last = ip, ip = ip->next) {
- if (ip->addr == addr) {
- if (last != NULLIPH) {
- /* Move entry to top of list */
- last->next = ip->next;
- ip->next = Iph;
- Iph = ip;
- }
- return ip;
- }
- }
- return NULLIPH;
- }
-
-
-
- /* Create a new entry in the source database */
- /* If there are too many entries, override the oldest one - WG7J */
- static struct iph *
- iph_create (uint32 addr)
- {
- static int numdb = 0;
- register struct iph *iph;
- struct iph *last = NULLIPH;
-
- if (Maxipheard && numdb == Maxipheard) {
- /* find and use last one in list */
- for (iph = Iph; iph->next != NULLIPH; last = iph, iph = iph->next)
- ;
- /* delete entry from end */
- if (last != NULLIPH)
- last->next = NULLIPH;
- } else { /* create a new entry */
- numdb++;
- #ifdef POOLED
- iph = (struct iph *) pool_alloc (&iph_pool);
- #else
- iph = (struct iph *) callocw (1, sizeof (struct iph));
-
- #endif
- }
- iph->addr = addr;
- iph->next = Iph;
- Iph = iph;
-
- return iph;
- }
-